﻿namespace OneWorks.Utils.Metadata
{
    using System;
    using System.Collections.Generic;
    using System.Data;
    using System.Linq;

    using Entity;

    using FluentData;

    using Interface;

    using IDataReader = FluentData.IDataReader;

    public class SqlServerMetadata : MetadataHandler
    {
        public SqlServerMetadata(IConnection connection)
            : base(new SqlServerProvider(), connection)
        {
        }

        protected override string GetDataBaseSting()
        {
            return "Select Name FROM Master..SysDatabases order by Name";
        }

        protected override string GetDataTableString(string dbName = "")
        {
            string sql = "";
            if (!string.IsNullOrEmpty(dbName))
            {
                sql += " USE " + dbName + " ";
            }


            sql += "SELECT " +
                  " Name = case when a.colorder = 1 then d.name else '' end," + //表名称
                  " Description = case when a.colorder = 1 then isnull(f.value, '') else '' end " + //表说明
                  " FROM syscolumns a " +
                  " inner join sysobjects d on a.id = d.id and d.xtype = 'U' and d.name <> 'sys.extended_properties' " +
                  " left join sys.extended_properties f on a.id = f.major_id and f.minor_id = 0 " +
                  " Where (case when a.colorder = 1 then d.name else '' end) <>''";
            return sql;
        }

        protected override string GetDataColumnString(string tbName, string dbName = "")
        {
            string sql = "";
            if (!string.IsNullOrEmpty(dbName))
            {
                sql += " USE " + dbName + " ";
            }
            sql = "SELECT  " +
                  "TableName= d.name," +
                  "Name = a.name, " +
                  "IsMarke =(case when COLUMNPROPERTY( a.id,a.name,'IsIdentity')=1 then '1'else '0' end)," +
                  "IsPrimarykey= (case when (SELECT count(*) FROM sysobjects WHERE (name in (SELECT name FROM sysindexes WHERE (id = a.id) AND (indid in (SELECT indid FROM sysindexkeys WHERE (id = a.id) AND (colid in (SELECT colid FROM syscolumns WHERE (id = a.id) AND (name = a.name))))))) AND (xtype = 'PK'))>0 then '1' else '0' end)," +
                  "Type =b.name," +
                  "Bytes=a.length, " +
                  "Length=COLUMNPROPERTY(a.id,a.name,'PRECISION')," +
                  "DecimalPlaces = isnull(COLUMNPROPERTY(a.id,a.name,'Scale'),0)," +
                  "IsNull=(case when a.isnullable=1 then '1'else '0' end), " +
                  "DefaultValue=isnull(e.text,'')," +
                  "Explain=isnull(g.[value], ' ')" +
                  " FROM syscolumns a left join systypes b on a.xtype=b.xusertype inner join sysobjects d on a.id=d.id and d.xtype='U' and d.name<>'dtproperties' left join syscomments e on a.cdefault=e.id left join sys.extended_properties g on a.id=g.major_id AND a.colid=g.minor_id left join sys.extended_properties f on d.id=f.class and f.minor_id=0 where b.name is not null --WHERE d.name='" + tbName + "' --如果只查询指定表,加上此条件 order by a.id,a.colorder";
            return sql;
        }

        protected override void DoDataBase(Database database, IDataReader reader)
        {
            database = new Database { Name = reader.GetString("Name") };
        }

        protected override List<Table> DoTable(DataTable dataTable)
        {
            try
            {
                return
                Enumerable.Select(
                    dataTable.AsEnumerable(),
                    row =>
                    new Table
                    {
                        Name = row.Field<string>("Name"),
                        Description = row["Description"].ToString()
                    }).
                    ToList();
            }
            catch (Exception exception)
            {
                Log.LogHandler.Log.Error("获取元数据表列表出现问题", exception);
                throw;
            }

        }

        protected override List<Column> DoColumn(DataTable dataTable)
        {
            try
            {
                return
                  Enumerable.Select(
                      dataTable.AsEnumerable(),
                      row =>
                      new Column
                      {
                          Name = row.Field<string>("Name"),
                          DbType = row.Field<string>("Type"),
                          Description = row.Field<string>("Explain"),
                          IsForeignKey = false,
                          IsIdentity = row.Field<bool>("IsPrimarykey"),
                          IsNull = row.Field<bool>("IsNull"),
                          IsPrimaryKey = row.Field<bool>("IsPrimarykey")
                      }).
                      ToList();
            }
            catch (Exception exception)
            {
                Log.LogHandler.Log.Error("获取元数据列名列表出现问题", exception);
                throw;
            }

        }
    }
}
